/*
 * SvrTask.h
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */

#ifndef SVRTASK_H_
#define SVRTASK_H_

#include "smart_lock.h"
#include "link_list.h"
#include "hash_link_table.h"
#include "http.h"
#include "io_buf.h"
#include "SvrConfig.h"
#include "Svr_log.h"
#include "DbAccess.h"
#include "SvrFileManage.h"

#define IP_LEN 32
#define TASK_TIME_OUT 180
#define TASK_BUF_LIMT_COUNT 10
#define HearBeatBufSize  IO_CHUNK_SIZE * 4

/*
*task status
*/
enum TASK_STATUS
{
    TASK_CLOSE,
    TASK_RUN
};
/*
*task flag
*/
enum TASK_FLAG
{
    TASK_NONE,
    TASK_MARKER,
    TASK_ADD,
    TASK_DEL
};

/*
 *delivery task define
 */
#pragma pack()
struct delivery_task_node
{
	char 	 filename[FILE_MAX_PATH];
	uint64_t filetotalsize;
	uint64_t current_file_size;
	uint32_t remote_ipaddr;
	int      remote_port;
	uint64_t remote_hsize;
	time_t   start_time;/*start time*/
	time_t   heart_time;/*heart time*/
	TASK_STATUS status;
	TASK_FLAG   flag;
    bool     is_completed;
    bool     is_noticed;
    int      errorcode;
	/*
	 * file data cache
	 * */
	int fd;
	buf_chunk * file_data_buf;
	buf_chunk * tail;
	int buf_count;
	/**
	 * task lock
	 */
	smart_lock  *plock;

	/*
	 * node du-link list ptr
	 * */
	delivery_task_node *prev,*next;

	/*
	 * node hash table du2-link list ptr
	 * */
	char  key[GUID_LEN];
	long  key_index;/*object hash key*/
	delivery_task_node *hash_prev,*hash_next;

	/**
	 * task init
	 */
	delivery_task_node()
	{
		memset(filename,'\0',sizeof(filename));
		filetotalsize = 0;
		current_file_size = 0;
		remote_ipaddr = 0;
		remote_port = 0;
		remote_hsize = 0;
		start_time = time(NULL);
		heart_time = time(NULL);
		status = TASK_CLOSE;
		flag = TASK_NONE;
		is_completed = false;
		is_noticed = false;
		errorcode = 0;

		fd = INVALID_HANDLE_VALUE;
		file_data_buf = NULL;
		tail = file_data_buf;
		buf_count = 0;
		plock =  new smart_lock();

		prev = _NULL;
		next = _NULL;

		memset(key,'\0',sizeof(key));
		key_index = 0;
		hash_prev= _NULL;
		hash_next= _NULL;
	}
};


/*
 * server task class
 */
class SvrTask
{
public:
    SvrTask();
    ~SvrTask();

    TASK_STATUS     cdn_heartbeat_task;

    int init(SvrConfig * pconfig,Svr_log * plog,SvrFileManage * psvrfilemanage,DbAccess * pdbaccess,int init_task_size = DFLT_MIN_CONN_SIZ);

    /*
	* run function
	* run
	* */
    void run(long useconds);

    /*
    *svr heartbeat function
    */
    uint32_t struct_heartbeat_data(char * buf,size_t buf_len);
    uint32_t read_heartbeat_data(char * buf,size_t buf_len);
    uint32_t write_heartbeat_data(char * buf,size_t size,int flag);
    int handle_heartbeat_data();


	/*
	*find task
	*key: file name
	*/
    delivery_task_node* find_task(const char * key);

    /*
	*delivery_task_node resource count
	*/
	int get_task_count();
	int get_free_task_count();

	/*
	 *struct task request header
	 **/
	uint32_t struct_task_request_header(const char * key,char * buf,size_t buf_len);

	/**
	 *write task data
	 *key:task key
	 *data: task data
	 *data_len:task data len
	 *return :write len,0,write error,-1 task not exist
	 */
	int write_file_data(const char * key,char * data,size_t data_len);

    /**
     *task run close
     */
    int task_run_close(const char * key,int error_code = 0);

    /*
	*use it must be carefull
	*task_list_lock, lock do enter call,
	*when you usr completed,then call end_enter
	*/
    delivery_task_node * begin_enter(void);
	void end_enter(void);


	/**
	 * test
	 */
	void test(const char * filename,uint64_t size,const char * remote_ip,uint64_t remote_size);

protected:
    /*
    *delivery_task_node resource pool alloc
    */
    int alloc_node(delivery_task_node ** t);

    /**
     * free task buf
     **/
    int free_node_buf(delivery_task_node * t);

    /*
    *delivery_task_node resource pool free
    */
    int free_node(delivery_task_node * t);

    /**
     * create task file
     */
    bool create_task_file(delivery_task_node * t);

	/*
	*add task
	*if false,and auto free node
	*/
	bool add_task(delivery_task_node * t);

	/*
	*remove task
	*/
	int remove_task(const char * key);

private:
    SvrConfig  * pSvrconfig;
    Svr_log	   * pSvrlog;
    DbAccess   * pDbutils;
    SvrFileManage * pSvrFileUtils;

    /*task hash table list,only for find quick*/
    hash_link_table<delivery_task_node> task_table;
    link_list<delivery_task_node> task_list;
    smart_lock  task_list_lock;
    bool        lock_flag;
    int 		default_size;  /*init default size svr_session object*/

    /*free list*/
    link_list<delivery_task_node> free_list;
    smart_lock  free_list_lock;

    /**
     * file data buf pool
     */
    io_buf mempool;

    /*
     * heartbeat data
     * */
    char * heartbeat_buf;
    size_t heartbeat_buf_offset;
    size_t heartbeat_buf_size;

    /**
     * time tick
     */
    int task_time_tick;
};

#endif /* SVRTASK_H_ */
